/*! 
 * Ball - Implementation file.
 *
 * \author Devis Rossini
 * \date 02 April 2012
 */
#include "PhxOgreBall.h"

using namespace GameObjects;

//-------------------------------------------------------------------------------------
Ball::Ball(phx::Scene* iScene, Ogre::SceneManager* iSceneManager, Ogre::SceneNode* iParentNode, 
	const Ogre::Vector3& iPokeBallPosition, const Ogre::Quaternion& iPokeBallOrientation, const float iPokeBallRadius, const float iPokeBallMass) 
{
	// Create the physical object.
	mPhxEntity = CreatePhxEntity(	iScene, 
									PhxOgreUtils::PhxVector3(iPokeBallPosition), 
									PhxOgreUtils::PhxQuaternion(iPokeBallOrientation), 
									iPokeBallRadius, 
									iPokeBallMass);

	// Create the Ogre's entity associated to the ball and insert it into the scenegraph.
	mSceneNode = CreateOgreEntity(	iSceneManager, 
									iParentNode, 
									iPokeBallPosition, 
									iPokeBallOrientation, 
									iPokeBallRadius, 
									iPokeBallMass);
}

//-------------------------------------------------------------------------------------
void Ball::Update(const float iDuration)
{
	// Update position/orientation of the scene node.
	phx::RigidBody* rigidBody = mPhxEntity->GetBody();

	phx::Vector3 ballPosition = rigidBody->GetPosition();
	mSceneNode->setPosition(PhxOgreUtils::OgreVector3(ballPosition));

	phx::Quaternion ballOrientation = rigidBody->GetOrientation();
	mSceneNode->setOrientation(PhxOgreUtils::OgreQuaternion(ballOrientation));
}

//-------------------------------------------------------------------------------------
phx::CollisionPrimitive* Ball::CreatePhxEntity(phx::Scene* iScene, const phx::Vector3& iBallPosition, const phx::Quaternion& iBallOrientation, 
	const phx::real iBallRadius, const phx::real iBallMass)
{
	phx::CollisionSphereDescriptor desc;
	desc.mPosition		= iBallPosition;
	desc.mOrientation	= iBallOrientation;
	desc.mMass			= iBallMass;

	// Intertia tensor.
	phx::Matrix3 sphereTensor;
	phx::real tensorCoeff = static_cast<phx::real>(0.4 * iBallMass * iBallRadius);
	sphereTensor.SetInertiaTensorCoeffs(tensorCoeff, tensorCoeff, tensorCoeff);

	desc.mInertiaTensor		= sphereTensor;
	desc.mLinearDamping		= 0.99f;
	desc.mAngularDamping	= 0.2f;
	desc.mAcceleration		= phx::Vector3::GRAVITY;
	desc.mVelocity			= phx::Vector3::ZERO;
	desc.mCanSleep			= true;
	desc.mIsAwake			= true;

	desc.mRadius			= static_cast<phx::real>(iBallRadius);

	// Create the collision entity.
	return iScene->CreatePrimitive(desc);
}

//-------------------------------------------------------------------------------------
Ogre::SceneNode* Ball::CreateOgreEntity(Ogre::SceneManager* iSceneManager, Ogre::SceneNode* iParentNode, 
	const Ogre::Vector3& iBallPosition, const Ogre::Quaternion& iBallOrientation, const float iBallRadius, const float iBallMass)
{
	Ogre::Entity* ballEntity = iSceneManager->createEntity("BallEntity", "nxogre.orb.mesh");
	ballEntity->getSubEntity(0)->setMaterialName("nxogre.orb2");
	Ogre::SceneNode* ballNode = iParentNode->createChildSceneNode("BallNode");

	// Scale the node according to the ball radius.
	ballNode->setScale(1, 1, 1);
	// Set position and orientation.
	ballNode->setPosition(iBallPosition);
	ballNode->setOrientation(iBallOrientation);

	// Attach the entity.
	ballNode->attachObject(ballEntity);

	return ballNode;
}